#ifndef __GLES2Texture_H__
#define __GLES2Texture_H__

#include "GLES2Support.h"
#include "Platform.h"
#include "RenderTexture.h"
#include "Texture.h"
#include "HardwarePixelBuffer.h"

namespace PVM
{
	class GLES2Texture : public Texture
	{
	public:
		GLES2Texture(ResourceManager* creator, const std::string& name, ResourceHandle handle,
					 const std::string& group, bool isManual, ManualResourceLoader* loader,
					 GLES2Support& support);
		
		virtual ~GLES2Texture();
		
		void createRenderTexture();
		
		HardwarePixelBufferSharedPtr getBuffer(size_t face, size_t mipmap);
		
		GLenum getGLES2TextureTarget(void) const;
		
		GLuint getGLID() const
		{
			return mTextureID;
		}
		
	protected:
		void createInternalResourcesImpl(void);
		void prepareImpl(void);
		void unprepareImpl(void);
		void loadImpl(void);
		void freeInternalResourcesImpl(void);
		
		void _createSurfaceList();
		typedef SharedPtr<vector<Image>::type> LoadedImages;
		
		LoadedImages mLoadedImages;
		
	private:
		GLuint mTextureID;
		GLES2Support& mGLSupport;
		
		typedef vector<HardwarePixelBufferSharedPtr>::type SurfaceList;
		SurfaceList mSurfaceList;
	};
	
	class GLES2TexturePtr : public SharedPtr<GLES2Texture>
	{
	public:
		GLES2TexturePtr() : SharedPtr<GLES2Texture>() {}
		explicit GLES2TexturePtr(GLES2Texture* rep) : SharedPtr<GLES2Texture>(rep) {}
		GLES2TexturePtr(const GLES2TexturePtr& r) : SharedPtr<GLES2Texture>(r) {}
		
		GLES2TexturePtr(const ResourcePtr& r) : SharedPtr<GLES2Texture>()
		{
			MUTEX_CONDITIONAL(r.AUTO_MUTEX_NAME)
			{
				LOCK_MUTEX(*r.AUTO_MUTEX_NAME);
				COPY_AUTO_SHARED_MUTEX(r.AUTO_MUTEX_NAME);
				pRep = static_cast<GLES2Texture*>(r.getPointer());
				pUseCount = r.useCountPointer();
				if (pUseCount)
				{
					++(*pUseCount);
				}
			}
		}
		
		GLES2TexturePtr(const TexturePtr& r) : SharedPtr<GLES2Texture>()
		{
			*this = r;
		}
		
		GLES2TexturePtr& operator=(const ResourcePtr& r)
		{
			if (pRep ==  static_cast<GLES2Texture*>(r.getPointer()))
			{
				return *this;
			}
			release();
			
			MUTEX_CONDITIONAL(r.AUTO_MUTEX_NAME)
			{
				LOCK_MUTEX(*r.AUTO_MUTEX_NAME)
				COPY_AUTO_SHARED_MUTEX(r.AUTO_MUTEX_NAME)
				pRep = static_cast<GLES2Texture*>(r.getPointer());
				pUseCount = r.useCountPointer();
				if (pUseCount)
				{
					++(*pUseCount);
				}
			}
			else
			{
				assert(r.isNull() && "RHS must be null if it has no mutex!");
				setNull();
			}
			return *this;
		}
		
		GLES2TexturePtr& operator = (const TexturePtr& r)
		{
			if (pRep == static_cast<GLES2Texture*>(r.getPointer()))
				return *this;
			release();
			
			MUTEX_CONDITIONAL(r.AUTO_MUTEX_NAME)
			{
				LOCK_MUTEX(*r.AUTO_MUTEX_NAME);
				COPY_AUTO_SHARED_MUTEX(r.AUTO_MUTEX_NAME);
				pRep = static_cast<GLES2Texture*>(r.getPointer());
				pUseCount = r.useCountPointer();
				if (pUseCount)
				{
					++(*pUseCount);
				}
			}
			else
			{
				assert(r.isNull() && "RHS must be null if it has no mutex!");
				setNull();
			}
			return *this;
		}
	};
}

#endif
